<template>
  <el-alert
    :title="$t('pageDateTime.alert.message')"
    :closable="false"
    type="info"
    center
    show-icon
  >
    <el-link href="/#/profile-settings" target="_self" type="danger">{{
      $t('pageDateTime.alert.link')
    }}</el-link>
  </el-alert>
  <dl>
    <dt>{{ $t('pageDateTime.form.Time') }}</dt>
    <dd v-if="bmcTime">{{ globalStore.formatDateTime(bmcTime) }}</dd>
    <dd v-else>--</dd>
  </dl>
  <h2 class="mt-6 text-base font-semibold leading-7 text-gray-900">
    {{ $t('pageDateTime.configureSettings') }}
  </h2>
  <el-form ref="formRef" :model="form" :rules="rules">
    <el-select
      v-model="form.configurationSelected"
      class="mt-2 mb-2 w-40"
      placeholder="Select"
      size="large"
    >
      <el-option
        key="manual"
        :label="$t('pageDateTime.form.manual')"
        value="manual"
      />
      <el-option key="ntp" label="NTP" value="ntp" />
    </el-select>
    <div v-if="form.configurationSelected === 'manual'">
      <el-row>
        <el-col :span="8">
          <el-form-item
            :label="$t('pageDateTime.form.date')"
            prop="manual.date"
          >
            <el-date-picker
              v-model="form.manual.date"
              type="date"
              placeholder="Pick a day"
              value-format="YYYY-MM-DD"
            />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item
            :label="$t('pageDateTime.form.time.timezone', { timezone })"
            prop="manual.time"
          >
            <el-time-picker
              v-model="form.manual.time"
              placeholder="Arbitrary time"
              format="HH:mm"
              value-format="HH:mm"
            />
          </el-form-item>
        </el-col>
      </el-row>
    </div>
    <div v-if="form.configurationSelected === 'ntp'">
      <el-row>
        <el-col :span="8">
          <el-form-item
            :label="$t('pageDateTime.form.ntpServers.server1')"
            prop="ntp.firstAddress"
          >
            <el-input
              v-model="form.ntp.firstAddress"
              class="ml-5 w-20"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="$t('pageDateTime.form.ntpServers.server2')">
            <el-input
              v-model="form.ntp.secondAddress"
              class="ml-5 w-20"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item :label="$t('pageDateTime.form.ntpServers.server3')">
            <el-input
              v-model="form.ntp.thirdAddress"
              class="ml-5 w-20"
            ></el-input>
          </el-form-item>
        </el-col>
      </el-row>
    </div>

    <el-button type="primary" @click="submitForm" class="mt-2">
      {{ $t('global.action.saveSettings') }}
    </el-button>
  </el-form>
</template>

<script setup lang="ts">
import { useGlobalStore } from '@/store/global';
import { useDateTimeStoreStore } from '@/store/Settings/DateTimeStore';
import useLocalTimeZone from '@/hooks/useLocalTimezoneLabel';
import useVuelidateTool from '@/hooks/useVuelidateTool';

const { useVuelidate, requiredIf, pattern, elementInputValidator } =
  useVuelidateTool();

const isoDateRegex = /([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/;
const isoTimeRegex = /^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/;

const dateTimeStore = useDateTimeStoreStore();
const globalStore = useGlobalStore();
const { localOffset } = useLocalTimeZone();

const form = reactive({
  configurationSelected: 'manual',
  manual: {
    date: '',
    time: '',
  },
  ntp: { firstAddress: '', secondAddress: '', thirdAddress: '' },
});

const v$ = useVuelidate(
  {
    manual: {
      date: {
        required: requiredIf(function () {
          return form.configurationSelected === 'manual';
        }),
        pattern: pattern.value(isoDateRegex),
      },
      time: {
        required: requiredIf(function () {
          return form.configurationSelected === 'manual';
        }),
        pattern: pattern.value(isoTimeRegex),
      },
    },
    ntp: {
      firstAddress: {
        required: requiredIf(function () {
          return form.configurationSelected === 'ntp';
        }),
      },
    },
  },
  form,
);

// validators
const rules = computed(() => {
  return {
    manual: {
      date: {
        trigger: 'change',
        validator: elementInputValidator.value(v$, 'manual.date'),
      },
      time: {
        trigger: 'change',
        validator: elementInputValidator.value(v$, 'manual.time'),
      },
    },
    ntp: {
      firstAddress: {
        trigger: 'change',
        validator: elementInputValidator.value(v$, 'ntp.firstAddress'),
      },
    },
  };
});

onMounted(() => {
  setNtpValues();
  globalStore.getBmcTime();
  dateTimeStore.getNtpData();
});

const formRef = ref();
const ntpServers = computed(() => dateTimeStore.ntpServers);
const isNtpProtocolEnabled = computed(() => dateTimeStore.isNtpProtocolEnabled);
const bmcTime = computed(() => globalStore.bmcTime);

const isUtcDisplay = computed(() => globalStore.isUtcDisplay);
const timezone = computed(() => (isUtcDisplay.value ? 'UTC' : localOffset()));

const setNtpValues = () => {
  form.configurationSelected = isNtpProtocolEnabled.value ? 'ntp' : 'manual';
  [
    form.ntp.firstAddress = '',
    form.ntp.secondAddress = '',
    form.ntp.thirdAddress = '',
  ] = [ntpServers.value[0], ntpServers.value[1], ntpServers.value[2]];
};

const submitForm = () => {
  v$.value.$touch();
  if (v$.value.$invalid) {
    formRef.value.validate();
    return;
  }

  let dateTimeForm: {
    ntpProtocolEnabled?: boolean;
    updatedDateTime?: string;
    ntpServersArray?: string[];
  } = {};
  let isNTPEnabled = form.configurationSelected === 'ntp';

  if (!isNTPEnabled) {
    const isUtcDisplay = globalStore.isUtcDisplay;
    let date;

    dateTimeForm.ntpProtocolEnabled = false;

    if (isUtcDisplay) {
      // Create UTC Date
      date = getUtcDate(form.manual.date, form.manual.time);
    } else {
      // Create local Date
      date = new Date(`${form.manual.date} ${form.manual.time}`);
    }

    dateTimeForm.updatedDateTime = date.toISOString();
  } else {
    dateTimeForm.ntpProtocolEnabled = true;

    dateTimeForm.ntpServersArray = [
      form.ntp.firstAddress,
      form.ntp.secondAddress,
      form.ntp.thirdAddress,
    ];
  }

  dateTimeStore
    .updateDateTime(dateTimeForm)
    .then((success: string) => {
      ElNotification({
        title: 'Success',
        message: success,
        type: 'success',
      });
      if (!isNTPEnabled) return;
      // Shift address up if second address is empty
      // to avoid refreshing after delay when updating NTP
      if (!form.ntp.secondAddress && form.ntp.thirdAddress) {
        form.ntp.secondAddress = form.ntp.thirdAddress;
        form.ntp.thirdAddress = '';
      }
    })
    .then(() => {
      globalStore.getBmcTime();
    })
    .catch(({ message }: { message: string }) =>
      ElNotification({
        title: 'Error',
        message,
        type: 'error',
      }),
    );
};

const getUtcDate = (date: string, time: string) => {
  // Split user input string values to create
  // a UTC Date object
  const datesArray = date.split('-');
  const timeArray = time.split(':');
  let utcDate = Date.UTC(
    datesArray[0] as unknown as number, // User input year
    //UTC expects zero-index month value 0-11 (January-December)
    //for reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC#Parameters
    parseInt(datesArray[1]) - 1, // User input month
    datesArray[2] as unknown as number, // User input day
    timeArray[0] as unknown as number, // User input hour
    timeArray[1] as unknown as number, // User input minute
  );
  return new Date(utcDate);
};

watch(ntpServers, () => {
  setNtpValues();
});

watch(bmcTime, () => {
  form.manual.date = globalStore.formatDate(globalStore.bmcTime as Date);
  form.manual.time =
    globalStore
      .formatDateTime(globalStore.bmcTime as Date)
      .split(' ')[1]
      .split(':')[0] +
    ':' +
    globalStore
      .formatDateTime(globalStore.bmcTime as Date)
      .split(' ')[1]
      .split(':')[1];
});
</script>
